package ph.com.gs3.formalistics.services.synchronizers;

import java.util.ArrayList;
import java.util.List;

import ph.com.gs3.formalistics.global.constants.LoggingType;
import ph.com.gs3.formalistics.global.constants.StarMark;
import ph.com.gs3.formalistics.model.LocalDataAccessObject.DeleteFailedException;
import ph.com.gs3.formalistics.model.RemoteDataAccessObject.RDAOCommunicationException;
import ph.com.gs3.formalistics.model.ldao.OutgoingActionsLDAO;
import ph.com.gs3.formalistics.model.rdao.DocumentsRDAO;
import ph.com.gs3.formalistics.model.vo.application.APIResponse.APIInvalidResponseException;
import ph.com.gs3.formalistics.model.vo.business.User;
import ph.com.gs3.formalistics.model.vo.business.document.SubmitReadyAction;
import ph.com.gs3.formalistics.services.synchronizers.exceptions.SynchronizationFailedException;
import ph.com.gs3.formalistics.services.synchronizers.exceptions.SynchronizationPrematureException;
import android.content.Context;

public class OutgoingActionsSynchronizer extends AbstractSynchronizer<Void> {

	public static final String TAG = OutgoingActionsSynchronizer.class.getSimpleName();
	public static LoggingType LOGGING_TYPE;

	private OutgoingActionsLDAO outgoingActionsLDAO;
	private DocumentsRDAO documentsRDAO;

	private User currentUser;

	public OutgoingActionsSynchronizer(Context context, User currentUser) {
		super(TAG, LOGGING_TYPE == null ? LoggingType.DISABLED : LOGGING_TYPE);

		this.currentUser = currentUser;

		outgoingActionsLDAO = new OutgoingActionsLDAO(context);

		documentsRDAO = new DocumentsRDAO(currentUser.getCompany().getServer());

	}

	@Override
	public Void synchronize() throws SynchronizationPrematureException {

		List<SynchronizationFailedException> synchFailures = new ArrayList<>();
		List<SubmitReadyAction> submitReadyActions = null;

		try {
			outgoingActionsLDAO.open();
			submitReadyActions = outgoingActionsLDAO.getAllSubmitReadyOutgoingActions(currentUser
			        .getId());

			for (SubmitReadyAction submitReadyAction : submitReadyActions) {

				String formWebId = submitReadyAction.getFormWebId();
				String documentWebId = submitReadyAction.getDocumentWebId();

				try {

					// TODO: make a combined API request for submitting documents and
					// changing star marks

					// Check if this action is about submitting a document
					if (!SubmitReadyAction.ACTION_NO_DOCUMENT_SUBMISSION.equals(submitReadyAction
					        .getAction())) {
						documentsRDAO.submitDocumentAction(formWebId, documentWebId,
						        submitReadyAction.getFieldUpdates(), submitReadyAction.getAction());
					}

					// Check if the document must be marked as starred/unstarred
					if (submitReadyAction.getIsStarredCode() != SubmitReadyAction.STAR_MARK_CODE_NO_ACTION) {

						if (submitReadyAction.getIsStarredCode() == SubmitReadyAction.STAR_MARK_CODE_UNSTAR) {
							documentsRDAO.markDocumentStar(formWebId, documentWebId,
							        StarMark.UNSTARRED);
						} else if (submitReadyAction.getIsStarredCode() == SubmitReadyAction.STAR_MARK_CODE_STAR) {
							documentsRDAO.markDocumentStar(formWebId, documentWebId,
							        StarMark.STARRED);
						}
					}

					// Remove the outgoing action from the database upon success
					removeOutgoingAction(submitReadyAction.getId());

				} catch (APIInvalidResponseException | RDAOCommunicationException e) {

					// Save the error message about the outgoing action to the database
					// upon fail
					setOutgoingActionError(e.getMessage());
					synchFailures.add(new SynchronizationFailedException(e));
				}
			}

		} finally {
			outgoingActionsLDAO.close();
		}

		return null;
	}

	private void removeOutgoingAction(int id) {
		try {
			outgoingActionsLDAO.open();
			outgoingActionsLDAO.removeOutgoingAction(id);
		} catch (DeleteFailedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			outgoingActionsLDAO.close();
		}
	}

	private void setOutgoingActionError(String errorMessage) {
		// TODO: implementation
	}
}
